import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.security.Key;
import java.util.Scanner;
import java.net.*;
public class Client5_5 {
    public static void main(String[] args) {
        String mode = "AES";
        //客户端让用户输入中缀表达式，然后把中缀表达式调用MyBC.java的功能转化为后缀表达式，把后缀表达式通过网络发送给服务器
        Scanner scanner = new Scanner(System.in);
        Socket mysocket;
        DataInputStream in = null;
        DataOutputStream out = null;
        try {
            mysocket = new Socket("127.0.0.1", 2010);
            in = new DataInputStream(mysocket.getInputStream());
            out = new DataOutputStream(mysocket.getOutputStream());
            System.out.println("请输入要计算的题目：");
            String formula = scanner.nextLine();
            String regex = ".*[^0-9|+|\\-|*|÷|(|)|\\s|/].*";
            if (formula.matches(regex)) {
                System.out.println("输入了非法字符");
                System.exit(1);
            }
            String output = "";
            MyBC myBC = new MyBC();
            try {
                output = myBC.getEquation(formula);//中缀转后缀
            } catch (ExprFormatException e) {
                System.out.println(e.getMessage());
                System.exit(1);
            }
            KeyGenerator kg = KeyGenerator.getInstance(mode);
            kg.init(128);
            SecretKey k = kg.generateKey();//生成密钥
            byte mkey[] = k.getEncoded();
            Cipher cp = Cipher.getInstance(mode);
            cp.init(Cipher.ENCRYPT_MODE, k);
            byte ptext[] = output.getBytes("UTF8");
            byte ctext[] = cp.doFinal(ptext);
            String out1 = B_H.parseByte2HexStr(ctext);//后缀表达式的加密
            out.writeUTF(out1);//将后缀表达式加密后传给Server

            Key_DH.createPubAndPriKey("Clientpub.txt","Clientpri.txt");


            FileInputStream fp = new FileInputStream("Clientpub.txt");
            ObjectInputStream bp = new ObjectInputStream(fp);
            Key kp = (Key) bp.readObject();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(kp);
            byte[] kb = baos.toByteArray();
            out.writeUTF(kb.length + "");
            for (int i = 0; i < kb.length; i++) {
                out.writeUTF(kb[i] + "");
            }
            Thread.sleep(1000);
            int len = Integer.parseInt(in.readUTF());
            byte np[] = new byte[len];
            for (int i = 0;i<len;i++) {
                String temp = in.readUTF();
                np[i] = Byte.parseByte(temp);
            }
            ObjectInputStream ois = new ObjectInputStream (new ByteArrayInputStream (np));
            Key k2 = (Key)ois.readObject();;
            FileOutputStream f2 = new FileOutputStream("Serverpub.txt");
            ObjectOutputStream b2 = new ObjectOutputStream(f2);
            b2.writeObject(k2);


            SecretKeySpec key = KeyAgree.createKey("Serverpub.txt", "Clientpri.txt");

            cp.init(Cipher.ENCRYPT_MODE, key);
            byte ckey[] = cp.doFinal(mkey);
            String Key = B_H.parseByte2HexStr(ckey);
            out.writeUTF(Key);//将密钥传给服务器

            String clientMD5 = DigestPass.digPass(output);
            out.writeUTF(clientMD5);
            String s = in.readUTF();//接收回答
            System.out.println("客户收到服务器的回答：" + s);
        } catch (Exception e) {
            System.out.println("服务器已断开" + e);
        }
    }
}

